package com.zbkj.service.coupons.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.zbkj.common.config.CrmebConfig;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.model.user.User;
import com.zbkj.common.model.user.UserBalanceRecord;
import com.zbkj.common.request.OrderPayRequest;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.result.OrderResultCode;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.service.coupons.request.BalanceToCouponRequest;
import com.zbkj.service.coupons.service.CouponsPayService;
import com.zbkj.service.dividend.event.DividendPoolEventPublisher;
import com.zbkj.service.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;

@Service
public class CouponsPayServiceImpl implements CouponsPayService {

    private static final Logger logger = LoggerFactory.getLogger(CouponsPayServiceImpl.class);

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private CrmebConfig crmebConfig;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private UserBalanceRecordService userBalanceRecordService;

    @Autowired
    private OrderFlowRecordService orderFlowRecordService;

    @Autowired
    private AsyncService asyncService;

    @Autowired
    private DividendPoolEventPublisher dividendPoolEventPublisher;


    /**
     * 订单支付
     *
     * @param orderPayRequest 订单支付参数
     * @return OrderPayResultResponse
     */
    @Override
    public OrderPayResultResponse payment(OrderPayRequest orderPayRequest) {
        Order order = orderService.getByOrderNo(orderPayRequest.getOrderNo());
        if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
            throw new CrmebException(OrderResultCode.ORDER_CANCEL);
        }
        if (order.getPaid()) {
            throw new CrmebException(OrderResultCode.ORDER_PAID);
        }
        if (order.getStatus() > OrderConstants.ORDER_STATUS_WAIT_PAY) {
            throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL);
        }
        User user = userService.getInfo();
        // 根据支付类型进行校验,更换支付类型
        order.setPayType("coupons");
        order.setPayChannel("coupons");
        // 获取过期时间 增加redis缓存的判断 2025-02-12
        DateTime cancelTime;
        if (redisUtil.exists(redisUtil.get(StrUtil.format(RedisConstants.ORDER_EXPIRE_TIME, order.getOrderNo())))) {
            String expireTime = redisUtil.get(StrUtil.format(RedisConstants.ORDER_EXPIRE_TIME, order.getOrderNo()));
            cancelTime = DateUtil.parseDateTime(expireTime);
        } else {
            cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
        }
        long between = DateUtil.between(cancelTime, DateUtil.date(), DateUnit.SECOND, false);
        if (between > 0) {
            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "订单已过期");
        }


        if (user.getCoupons().compareTo(order.getPayPrice()) < 0) {
            throw new CrmebException("消费券余额不足");
        }


        OrderPayResultResponse response = new OrderPayResultResponse();
        response.setOrderNo(order.getOrderNo());
        response.setPayType(order.getPayType());
        response.setPayChannel(order.getPayChannel());
        if (!order.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_NORMAL)) {
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "支付金额不能低于等于0元");
            }
        }
        // 消费券支付
        if (order.getPayType().equals("coupons") || order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
            Boolean couponsBoolean = pay(order, user);
            response.setStatus(couponsBoolean);
            return response;
        }
        response.setStatus(false);
        return response;
    }

    /**
     * 消费券支付
     *
     * @param order 订单
     * @return Boolean Boolean
     */
    private Boolean pay(Order order, User user) {
        // 用户消费券余额扣除
        Boolean execute = transactionTemplate.execute(e -> {
            Boolean update = Boolean.TRUE;
            // 订单修改
            order.setPaid(true);
            order.setPayTime(DateUtil.date());
            order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
            order.setPayType(order.getPayType());
            order.setPayChannel(order.getPayChannel());
            order.setUpdateTime(DateUtil.date());
            orderService.updateById(order);
            // 这里只扣除消费券金额，账单记录在task中处理
            BigDecimal coupons = user.getCoupons().subtract(order.getPayPrice());
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                User updateUserInfo = new User();
                updateUserInfo.setId(user.getId());
                updateUserInfo.setCoupons(coupons);
                update = userService.updateById(updateUserInfo);
                if (!update) {
                    logger.error("消费券余额支付，扣除用户消费券余额失败，orderNo = {}", order.getOrderNo());
                    e.setRollbackOnly();
                    return update;
                }
                // 用户余额记录
                UserBalanceRecord userBalanceRecord = new UserBalanceRecord();
                userBalanceRecord.setUid(user.getId());
                userBalanceRecord.setLinkId(order.getOrderNo());
                userBalanceRecord.setLinkType(BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
                userBalanceRecord.setType(BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
                userBalanceRecord.setAmount(order.getPayPrice());
                userBalanceRecord.setBalance(coupons);
                userBalanceRecord.setRemark(StrUtil.format("用户订单付款成功,扣消费券余额{}元", order.getPayPrice()));
                userBalanceRecordService.save(userBalanceRecord);
            }
            orderFlowRecordService.orderPaid(order.getOrderNo(), order.getUid());
            return update;
        });
        if (!execute) throw new CrmebException("消费券余额支付订单失败");
        asyncService.orderPaySuccessSplit(order.getOrderNo());
        //发布分红事件
        dividendPoolEventPublisher.publishDividendEvent(order);
        return true;
    }

    @Override
    public String balanceToCoupons(BalanceToCouponRequest request) {
        try {
            User user = userService.getInfo();
            if (user.getNowMoney().compareTo(request.getExchangeAmount()) < 0) return "储值余额不足";
            User updateUser = new User();
            updateUser.setId(user.getId());
            updateUser.setNowMoney(user.getNowMoney().subtract(request.getExchangeAmount()));
            updateUser.setCoupons(user.getCoupons().add(request.getExchangeAmount()));


            boolean updateFlag;
            updateFlag = userService.updateById(updateUser);
            //分红池变更
            dividendPoolEventPublisher.publishDividendChangeEvent(user.getId(), updateUser.getNowMoney(),"分红池调整变更");

            return updateFlag ? "兑换成功" : "兑换失败";
        } catch (Exception e) {
            return "兑换失败";
        }
    }
}
